package com.su.lightthings.bluetooth

import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothGatt
import android.util.Log
import com.jieli.jl_bt_ota.constant.BluetoothConstant
import com.jieli.jl_bt_ota.util.BluetoothUtil
import com.su.lightthings.ble.BleManager
import com.su.lightthings.ble.interfaces.BleEventCallback
import com.su.lightthings.ble.model.BleScanInfo
import com.su.lightthings.bluetooth.OnBTEventCallback
import com.su.lightthings.utils.AppUtil
import com.su.lightthings.utils.ByteUtils
import com.su.lightthings.utils.Cons
import com.su.lightthings.utils.OtaConstant
import java.util.UUID

/**
 * @author zqjasonZhong
 * @since 2022/9/14
 * @email zhongzhuocheng@zh-jieli.com
 * @desc 蓝牙操作辅助类
 */
class BluetoothHelper {

    private val bleManager = BleManager.getInstance()!!
    private val btEventCbHelper = BTEventCbHelper()

    companion object {

        const val TAG: String = "BluetoothHelper"

        @Volatile
        private var instance: BluetoothHelper? = null

        fun getInstance(): BluetoothHelper = instance ?: synchronized(this) {
            instance ?: BluetoothHelper().also { instance = it }
        }
    }

    private val bleEventCallback = object : BleEventCallback() {

        override fun onAdapterChange(bEnabled: Boolean) {
            btEventCbHelper.onAdapterChange(bEnabled)
        }

        override fun onDiscoveryBleChange(bStart: Boolean) {
            btEventCbHelper.onDiscoveryChange(bStart, OtaConstant.PROTOCOL_BLE)
        }

        override fun onDiscoveryBle(device: BluetoothDevice?, bleScanMessage: BleScanInfo?) {
            btEventCbHelper.onDiscovery(device, bleScanMessage)
        }

        override fun onBleConnection(device: BluetoothDevice?, status: Int) {
            btEventCbHelper.onDeviceConnection(device, OtaConstant.PROTOCOL_BLE, status)
        }

        override fun onBleDataNotification(
            device: BluetoothDevice?,
            serviceUuid: UUID?,
            characteristicsUuid: UUID?,
            data: ByteArray?
        ) {
            btEventCbHelper.onReceiveData(
                device,
                OtaConstant.PROTOCOL_BLE,
                characteristicsUuid,
                data
            )
        }

        override fun onBleDataBlockChanged(device: BluetoothDevice?, block: Int, status: Int) {
            btEventCbHelper.onBleMtuChange(device, block, status)
        }
    }

    init {
        bleManager.registerBleEventCallback(bleEventCallback)
    }

    fun destroy() {
        bleManager.unregisterBleEventCallback(bleEventCallback)
        bleManager.destroy()
        btEventCbHelper.release()
        instance = null
    }

    fun registerCallback(callback: OnBTEventCallback) {
        btEventCbHelper.registerCallback(callback)
    }

    fun unregisterCallback(callback: OnBTEventCallback) {
        btEventCbHelper.unregisterCallback(callback)
    }

    fun isConnected(): Boolean {
        return getConnectedDevice() != null
    }

    fun isDeviceConnected(device: BluetoothDevice?): Boolean {
        return BluetoothUtil.deviceEquals(getConnectedDevice(), device)
    }

    fun isScanning(): Boolean = bleManager.isBleScanning

    fun isConnecting(): Boolean = bleManager.isBleScanning

    fun getConnectedDevice(): BluetoothDevice? = bleManager.connectedBtDevice

    fun getConnectedGatt(): BluetoothGatt? = bleManager.getConnectedBtGatt(getConnectedDevice())


    fun getBleMtu(): Int = bleManager.getBleMtu(getConnectedDevice())

    fun startScan(timeout: Long): Boolean =
        bleManager.startLeScan(timeout)

    fun stopScan() = bleManager.stopLeScan()


    fun connectDevice(device: BluetoothDevice?): Boolean =
        bleManager.connectBleDevice(device)

    fun connectDevice(address: String): Boolean =
        bleManager.connectBleDevice(address)

    fun disconnectDevice(device: BluetoothDevice?) =
        bleManager.disconnectBleDevice(device)

    fun connectBleDevice(device: BluetoothDevice?): Boolean =
        bleManager.connectBleDevice(device)

    fun reconnectDevice(address: String?, isUseNewAdv: Boolean) =
        bleManager.reconnectDevice(address, isUseNewAdv)


    fun writeDataToDevice(bluetoothDevice: BluetoothDevice?, byteArray: ByteArray?): Boolean {
        if (null == bluetoothDevice || null == byteArray || byteArray.isEmpty()) return false
        if (bleManager.connectedBtDevice != null) {//目前连接的设备是ble
            bleManager.writeDataByBleAsync(
                bluetoothDevice,
                BleManager.BLE_UUID_SERVICE,
                BleManager.BLE_UUID_WRITE,
                byteArray
            ) { device, serviceUUID, characteristicUUID, result, data ->
                Log.i(
                    TAG,
                    "-writeDataByBleAsync- device:${
                        printDeviceInfo(device)
                    }, result = $result,\n serviceUUID = $serviceUUID , characteristicUUID = $characteristicUUID \ndata:[${
                        ByteUtils.toHexString(
                            data
                        )
                    }]"
                )
            }
        }
        return true
    }


    fun writeDataToDevice(
        bluetoothDevice: BluetoothDevice?,
        serviceUUID: UUID,
        characteristicUUID: UUID,
        byteArray: ByteArray?
    ): Boolean {
        if (null == bluetoothDevice || null == byteArray || byteArray.isEmpty()) return false
        if (bleManager.connectedBtDevice != null) {//目前连接的设备是ble
            bleManager.writeDataByBleAsync(
                bluetoothDevice,
                serviceUUID,
                characteristicUUID,
                byteArray
            ) { device, serviceUUID, characteristicUUID, result, data ->
                Log.i(
                    TAG,
                    "-writeDataByBleAsync- device:${
                        printDeviceInfo(device)
                    }, result = $result,\n serviceUUID = $serviceUUID , characteristicUUID = $characteristicUUID \ndata:[${
                        ByteUtils.toHexString(
                            data
                        )
                    }]"
                )
            }
        }
        return true
    }

    /**
     * 关闭常规事件监听
     */
    fun disableNormalBLEDeviceNotification() {
        bleManager.disableBLEDeviceNotification(
            Cons.BleUUID.BLE_UUID_SERVICE,
            Cons.BleUUID.BLE_UUID_NOTIFICATION
        )
    }

    /**
     * 关闭杰里OTA事件监听
     */
    fun disableJlBLEDeviceNotification() {
        bleManager.disableBLEDeviceNotification(
            BluetoothConstant.UUID_SERVICE,
            BluetoothConstant.UUID_NOTIFICATION
        )
    }

    /**
     * 开启常规事件监听
     */
    fun enableNormalBLEDeviceNotification() {
        bleManager.enableBLEDeviceNotification(
            Cons.BleUUID.BLE_UUID_SERVICE,
            Cons.BleUUID.BLE_UUID_NOTIFICATION
        )
    }

    /**
     * 开启杰里OTA事件监听
     */
    fun enableJlBLEDeviceNotification() {
        bleManager.enableBLEDeviceNotification(
            BluetoothConstant.UUID_SERVICE,
            BluetoothConstant.UUID_NOTIFICATION
        )
    }


    private fun printDeviceInfo(device: BluetoothDevice?): String? {
        return AppUtil.printBtDeviceInfo(device)
    }

}